import 'package:intl/intl.dart';

const String KDateTimeYMD = "yyyy-MM-dd";
const String KDateTimeZoonYMDHMS = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
const String KDateTimeMMDHM = "MMM dd HH:mm";
const String KDateTimeHM = "HH:mm";
const String KTCHourMinAAFormat = "HH:mmaa";
const String KRDTimeZoneMonthDayHourMinSecFormat = "yyyy-MM-dd'T'HH:mm:ss";


const String KDateTimeMMDYHM = "MMM dd yyyy HH:mm";

extension DateTimeExtension on DateTime {
  static List weeksList = [
    " ",
    "星期一",
    "星期二",
    "星期三",
    "星期四",
    "星期五",
    "星期六",
    "星期日"
  ];

  ///获取当月共有多少天
  int getMonthDay() {
    DateTime dateTime = this;
    DateTime nextDateTime = DateTime(dateTime.year, dateTime.month + 1, 1);
    DateTime currentDateTime = nextDateTime.add(const Duration(days: -1));
    return currentDateTime.day;
  }

  ///获取星期几
  String getWeekDay() {
    DateTime dateTime = this;
    return weeksList[dateTime.weekday];
  }

  /*根据年份获取周数*/
  static int numOfWeeks(int year) {
    DateTime dec28 = DateTime(2022, 12, 28);
    int dayOfDec28 = int.parse(DateFormat("D").format(dec28));
    return ((dayOfDec28 - dec28.weekday + 10) / 7).floor();
  }

  /*根据日期获取在当年的第几周*/
  static int weekNumber(DateTime date) {
    int dayOfYear = int.parse(DateFormat("D").format(date));
    int woy = ((dayOfYear - date.weekday + 10) / 7).floor();
    if (woy < 1) {
      woy = numOfWeeks(date.year - 1);
    } else if (woy > numOfWeeks(date.year)) {
      woy = 1;
    }
    return woy;
  }

  /* 根据第几周获取开始时间和结束时间*/
  static Map<String, String> getDateTimeStringFromWeekNumber(
      {required int year, required int weekNumber}) {
    int firstDayOfWeek = (weekNumber - 1) * 7;
    final extraDuration = Duration(days: firstDayOfWeek);

    final startDate = DateTime(year);
    Map<String, String> dateMap = {};
    final dates = startDate.add(extraDuration);
    DateTime? startTime;
    for (var i = 0; i < 8; i++) {
      var newDate = dates.add(Duration(days: i));
      if (DateFormat('EEEE').format(newDate) == 'Monday') {
        startTime = newDate;
        // dateMap.addAll({'startTime': newDate.toString()});
      } else if (DateFormat('EEEE').format(newDate) == 'Sunday') {
        // dateMap.addAll({'endTime': newDate.toString()});
      }
    }
    DateTime endTime = startTime!.add(const Duration(days: 6));
    endTime = endTime.add(const Duration(seconds: 86399));
    dateMap['endTime'] = DateFormat('yyyy-MM-dd HH:mm:ss').format(endTime);
    dateMap['startTime'] = DateFormat('yyyy-MM-dd HH:mm:ss').format(startTime);
    return dateMap;
  }

  static DateTime getMondayTimeFromDate(DateTime date) {
    int week = weekNumber(date);
    Map<String, String> map =
        getDateTimeStringFromWeekNumber(year: date.year, weekNumber: week);
    return DateFormat('yyyy-MM-dd HH:mm:ss').parse(map['startTime'] ?? '');
  }

  static String getEndMoth(int timeSamp, {format = "yyyy-MM-dd HH:mm:ss"}) {
    var dateFormat = DateFormat(format);
    var dateTime = DateTime.fromMillisecondsSinceEpoch(timeSamp);
    var dateNextMonthDate = DateTime(dateTime.year, dateTime.month + 1, 1);
    int nextTimeSamp =
        dateNextMonthDate.millisecondsSinceEpoch - 24 * 60 * 60 * 1000;
    //取得了下一个月1号码时间戳
    var dateTimeeee = DateTime.fromMillisecondsSinceEpoch(nextTimeSamp);
    dateTimeeee = dateTimeeee.add(Duration(seconds: 86399));
    String formartResult = dateFormat.format(dateTimeeee);
    return formartResult;
  }

  String formatTodayTimeStr({String? formatStr, bool isDetail = false}) {
    if (this == null) return "";
    DateTime nowTime = DateTime.now().toLocal();
    DateTime checkTime = this.toLocal();
    Duration diff = checkTime.difference(nowTime);

    if (checkTime.year != nowTime.year) {
      return checkTime.toDateStringWithFormat(formatStr ?? KDateTimeYMD);
    }
    if (((diff <= const Duration(hours: 0)) &&
            (diff > const Duration(hours: -24))) ||
        ((diff > const Duration(hours: 0)) &&
            (diff < const Duration(hours: 24)))) {
      return checkTime.toDateStringWithFormat("HH:mm");
    } else if ((diff < const Duration(hours: -24)) &&
        (diff > const Duration(hours: -24 * 2))) {
      if (isDetail) {
        String timeStr = checkTime.toDateStringWithFormat("HH:mm");
        return '昨天 ${timeStr}';
      } else {
        return "昨天";
      }
    } else if (diff < const Duration(hours: -24) &&
        diff > const Duration(hours: -24 * 7)) {
      if (isDetail) {
        return checkTime.toDateStringWithFormat("EEEE HH:mm");
      } else {
        return checkTime.toDateStringWithFormat("EEEE");
      }
    }

    if (isDetail) {
      return checkTime.toDateStringWithFormat("MM/dd HH:mm");
    } else {
      return checkTime.toDateStringWithFormat("MM/dd");
    }
  }

  String toDateStringWithFormat(String formatStr) {
    if (this == null) return "";
    DateFormat dateFormat = DateFormat(formatStr);

    String dateStr = dateFormat.format(this);

    return dateStr;
  }

  DateTime getFirstDayOfWeek({int sepWeek = 0}) {
    DateTime dateTime = this;
    int weekDay = dateTime.weekday;
    DateTime firstDayOfWeek =
        dateTime.subtract(Duration(days: weekDay - sepWeek * 7));
    return firstDayOfWeek;
  }

  DateTime getLastDayOfWeek({int sepWeek = 0}) {
    DateTime firstDayOfWeek = getFirstDayOfWeek(sepWeek: sepWeek);
    DateTime lastDayOfWeek = firstDayOfWeek.add(Duration(days: 6));
    return lastDayOfWeek;
  }

}

String timeStampToDateStringWithFormat(int timeStamp, String format) {
  DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timeStamp).toLocal();

  DateFormat dateFormat = DateFormat(format);

  String dateStr = dateFormat.format(dateTime);

  return dateStr;
}

String formatISOTime(DateTime date) {
  //converts date into the following format:
// or 2019-06-04T12:08:56.235-0700
  var duration = date.timeZoneOffset;
  if (duration.isNegative)
    return (DateFormat("yyyy-MM-ddTHH:mm:ss.SSS").format(date) +
        "-${duration.inHours.toString().padLeft(2, '0')}${(duration.inMinutes - (duration.inHours * 60)).toString().padLeft(2, '0')}");
  else
    return (DateFormat("yyyy-MM-ddTHH:mm:ss.SSS").format(date) +
        "+${duration.inHours.toString().padLeft(2, '0')}${(duration.inMinutes - (duration.inHours * 60)).toString().padLeft(2, '0')}");
}

bool checkTimesHasOverlap(DateTime dynaStartTime, DateTime dynaEndTime,
    DateTime fixedStartTime, DateTime fixedEndTime) {
  return !(dynaEndTime.isBefore(fixedStartTime) ||
      dynaStartTime.isAfter(fixedEndTime));
}

bool isDateTimeExpired(DateTime serverDateTime) {
  bool isExpired = false;
  DateTime currentDate = DateTime.now().toLocal();
  if (isSameDay(serverDateTime, currentDate)) {
    isExpired = false;
  } else if (serverDateTime.isBefore(currentDate)) {
    isExpired = true;
  } else {
    isExpired = false;
  }
  return isExpired;
}

bool isSameDay(DateTime serverDateTime, DateTime currentDate) {
  return serverDateTime.year == currentDate.year &&
      serverDateTime.month == currentDate.month &&
      serverDateTime.day == currentDate.day;
}
